﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace Ant.Update
{
    public partial class FrmMain : Form, Beetle.IMessageHandler
    {
        public FrmMain()
        {
            InitializeComponent();
        }
        private Beetle.TcpChannel mChannel;
        private Beetle.ChannelAdapter mAdapter;
        private System.Threading.AutoResetEvent mResetEvent = new System.Threading.AutoResetEvent(false);
        private Queue<Component.FileItem> mDownloads = null;
        private string tmpFolder = "";
        private int mUpateCount = 0;
        private Component.Protocols.GetResponse getResponse = null;
        public string[] Arges
        {
            get;
            set;
        }
        private Component.UpdateInfo mLocalInfo = new Component.UpdateInfo();
        private Component.UpdateInfo mUpdateInfo = new Component.UpdateInfo();
        private IList<Component.FileItem> mCopyFiles = new List<Component.FileItem>(100);
        private void Form1_Load(object sender, EventArgs e)
        {
            Beetle.TcpUtils.DataPacketMaxLength = 1024 * 128;
            Beetle.TcpUtils.SendBufferLength = 1024 * 8;
            Beetle.TcpUtils.Setup(10, 1, 1);
            Beetle.PacketAnalysis.Setup(1);
            tmpFolder = "tmp" + DateTime.Now.ToString("yyyyMMdd"); ;
            Utils.FileProgress.Draw("", 0, 100);
            Utils.TotalProgress.Draw("下载总进度 ", 0, 10);
            imgFile.Image = Utils.FileProgress.Image;
            imtTotal.Image = Utils.TotalProgress.Image;

            Utils.LoadINI();
            mLocalInfo.Load(Utils.GetFileFullName(Utils.UPDATE_FILE));

            System.Threading.ThreadPool.QueueUserWorkItem(Connect);


        }
        private void ChangeStatus(Color color, string text)
        {
            Invoke(new Smark.Core.AsyncDelegate<Color, string>((c, s) =>
            {
                txtStatus.ForeColor = c;
                txtStatus.Text = s;
            }), color, text);
        }
        protected void Connect(object state)
        {
            try
            {
                if (Arges.Length > 0)
                    Utils.IPAddress = Arges[0];
                if (Arges.Length > 1)
                    Utils.Port = Arges[1];
                if (Arges.Length > 2)
                    Utils.AppName = Arges[2];
                if (Arges.Length > 3)
                    Utils.AutoClose = Arges[3];
                if (string.IsNullOrEmpty(Utils.IPAddress))
                {
                    throw new Exception("不存在服务器地址信息!");
                }
                if (string.IsNullOrEmpty(Utils.Port))
                {
                    throw new Exception("不存在服务器地址信息!");
                }
                System.Net.IPAddress[] ips = System.Net.Dns.GetHostAddresses(Utils.IPAddress);
                if (ips == null || ips.Length == 0)
                    throw new Exception("访问地址无效!");
                mChannel = Beetle.TcpServer.CreateClient(ips[0].ToString(), int.Parse(Utils.Port));
                mAdapter = new Beetle.ChannelAdapter(mChannel,
                    new Beetle.HeadSizePackage(Component.Protocols.MessageBase.GetMessage));
                mAdapter.RegisterHandler(this);
                Component.Protocols.GetUpdateInfo update = new Component.Protocols.GetUpdateInfo();
                mChannel.BeginReceive();
                mAdapter.Send(update);
                ChangeStatus(Color.Black, "获取文件更新信息...");


            }
            catch (Exception e_)
            {
                ChangeStatus(Color.Red, e_.Message);
            }
        }
        private void OnError(object sender, Beetle.ChannelErrorEventArgs e_)
        {
            ChangeStatus(Color.Red, "程序处理错误:" + e_.Exception.Message);
        }
        private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            System.Diagnostics.Process.Start("explorer", "http://www.henryfan.net");
        }
        public void ProcessMessage(Beetle.ChannelAdapter adapter, Beetle.MessageHandlerArgs message)
        {

        }
        public void GetUpdateInfoResponse(Beetle.ChannelAdapter adapter, Component.Protocols.GetUpdateInfoResponse e)
        {
            if (string.IsNullOrEmpty(e.Status))
            {
                mUpdateInfo.LoadXml(e.Info);
                mDownloads = mLocalInfo.Comparable(mUpdateInfo);
                if (mDownloads.Count == 0)
                {
                    ChangeStatus(Color.Black, "当前是最新版本!");
                }
                else
                {
                    ChangeStatus(Color.Black, "下载文件到临时文件夹...");
                    mUpateCount = mDownloads.Count;
                    Utils.TotalProgress.Draw(string.Format("更新文件总进度 {0}/{1}", 0, mUpateCount), 0, mUpateCount);
                    string tmpf = Utils.GetFileFullName(tmpFolder);
                    if (!System.IO.Directory.Exists(tmpf))
                        System.IO.Directory.CreateDirectory(tmpf);
                    Get();
                }
            }
            else
            {
                ChangeStatus(Color.Red, e.Status);
            }
        }
        public void GetResponse(Beetle.ChannelAdapter adapter, Component.Protocols.GetResponse e)
        {
            if (string.IsNullOrEmpty(e.Status))
            {
                getResponse = e;
                Utils.TotalProgress.Draw(string.Format("下载总进度 {0}/{1}", mUpateCount - mDownloads.Count + 1, mUpateCount), mUpateCount - mDownloads.Count + 1, mUpateCount);
                Component.FileItem item = mDownloads.Peek();
                string path = System.IO.Path.GetDirectoryName(item.File);
                if (!string.IsNullOrEmpty(path))
                {
                    string createFolder = Utils.GetFileFullName(tmpFolder + "\\" + path);
                    if (!System.IO.Directory.Exists(createFolder))
                        System.IO.Directory.CreateDirectory(createFolder);

                }
                Component.FileUtils.CreateFile(Utils.GetFileFullName(tmpFolder + "\\" + item.File + ".update"), getResponse.Size);
                Component.Protocols.GetPackage getpackage = new Component.Protocols.GetPackage();
                getpackage.Index = 0;
                adapter.Send(getpackage);
            }
            else
            {
                ChangeStatus(Color.Red, e.Status);
            }
        }
        public void GetPackageResponse(Beetle.ChannelAdapter adpater, Component.Protocols.GetPackageResponse e)
        {
            try
            {
                Component.FileItem item = mDownloads.Peek();
                Utils.FileProgress.Draw(item.File, e.Index + 1, getResponse.Packages);
                Component.FileUtils.FileWrite(Utils.GetFileFullName(tmpFolder + "\\" + item.File + ".update"), e.Index, getResponse.PackageSize, e.Data);
                if (e.Index + 1 == getResponse.Packages)
                {
                    mCopyFiles.Add(mDownloads.Dequeue());
                    Get();
                }
                else
                {
                    Component.Protocols.GetPackage getpackage = new Component.Protocols.GetPackage();
                    getpackage.Index = e.Index + 1;
                    adpater.Send(getpackage);
                }
            }
            catch (Exception e_)
            {
                ChangeStatus(Color.Red, e_.Message);
            }
        }
        private void Get()
        {
            if (mDownloads.Count > 0)
            {
                Component.FileItem item = mDownloads.Peek();
                Component.Protocols.Get get = new Component.Protocols.Get();
                get.FileName = item.File;
                mAdapter.Send(get);

            }
            else
            {
                CopyTempFiles();
            }
        }
        private void CopyTempFiles()
        {
            ChangeStatus(Color.Black, "下载完成，更新本地文件...");
            foreach (Component.FileItem item in mCopyFiles)
            {
                string filename = Utils.GetFileFullName(item.File);
                if (System.IO.File.Exists(filename))
                    System.IO.File.Delete(filename);
                string path = System.IO.Path.GetDirectoryName(item.File);
                if (!string.IsNullOrEmpty(path))
                {
                    string createFolder = Utils.GetFileFullName(path);
                    if (!System.IO.Directory.Exists(createFolder))
                        System.IO.Directory.CreateDirectory(createFolder);

                }
                System.IO.File.Move(Utils.GetFileFullName(tmpFolder + "\\" + item.File + ".update"),
                    filename);
            }
            mLocalInfo.Save(Utils.GetFileFullName(Utils.UPDATE_FILE));
            System.IO.Directory.Delete(Utils.GetFileFullName(tmpFolder), true);
            ChangeStatus(Color.Black, "更新完成!");
            bool autoclose;
            System.Threading.Thread.Sleep(1000);
            if (bool.TryParse(Utils.AutoClose, out autoclose))
            {
                if (autoclose)
                {
                    Invoke(new Action<FrmMain>(f =>
                    {
                        f.Close();
                    }), this);
                }
            }
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            lock (Utils.FileProgress)
            {
                imgFile.Refresh();
            }
            lock (Utils.TotalProgress)
            {
                imtTotal.Refresh();
            }
        }

        private void FrmMain_FormClosed(object sender, FormClosedEventArgs e)
        {
            if (!string.IsNullOrEmpty(Utils.AppName))
                System.Diagnostics.Process.Start(Utils.AppName);
        }

        private void toolStripStatusLabel1_Click(object sender, EventArgs e)
        {
            System.Diagnostics.Process.Start("explorer", "http://www.henryfan.net");
        }
    }
}
